package org.yyds;

import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.Jedis;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class RedisPollingBackup2 {
    // 定义轮询间隔时间的常量
    private static final int POLLING_INTERVAL_MS = 100; // 轮询间隔时间，单位：毫秒

    // 定义需要监控的键的前缀
    private static final String[] KEY_PATTERNS = {"*"};

    public static void main(String[] args) {

        Jedis jedisMain = new Jedis("127.0.0.1", 6379);
        Jedis jedisBackup = new Jedis("127.0.0.1", 6379);
//        jedisMain.auth("");
//        jedisBackup.auth("");
        jedisMain.select(0);
        jedisBackup.select(1);

        // 清空备份 Redis 中的数据
        jedisBackup.flushDB();

        while (true) {
            try {
                Thread.sleep(POLLING_INTERVAL_MS); // 每隔100毫秒检查一次
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }

            // 获取主 Redis 中的所有键
            //Set<String> mainKeys = jedisMain.keys("*");
            Set<String> mainKeys = new HashSet<>(128);
            for (String pattern : KEY_PATTERNS) mainKeys.addAll(jedisMain.keys(pattern));

            // 获取备份 Redis 中的所有键
            Set<String> backupKeys = jedisBackup.keys("*");

            // 需要备份的新增键
            List<String> keysToBackup = mainKeys.stream()
                    .filter(key -> !backupKeys.contains(key)) // 找到主 Redis 有而备份 Redis 没有的键
                    .collect(Collectors.toList());

            // 需要恢复的被删除键
            List<String> keysToRestore = backupKeys.stream()
                    .filter(key -> !mainKeys.contains(key)) // 找到备份 Redis 有而主 Redis 没有的键
                    .collect(Collectors.toList());

            // 备份新增的键到备份 Redis
            keysToBackup.forEach(key -> {
                // 获取原始数据类型
                String dataType = jedisMain.type(key);
                // 备份数据
                if (dataType.equals("string")) {
                    // 如果是字符串类型，备份字符串数据
                    String value = jedisMain.get(key);
                    jedisBackup.set(key, value);
                    System.out.println("Backed up key: " + key);
                }
            });

            // 从备份 Redis 恢复被删除的键
            keysToRestore.forEach(key -> {
                String backupDataType = jedisBackup.type(key);
                if (backupDataType.equals("string")) {
                    // 如果备份数据也是字符串类型，将备份的值恢复到原始键
                    String value = jedisBackup.get(key);
                    jedisMain.set(key, value);
                    System.out.println("Restored key: " + key);
                }
            });


            List<String> keysToUpdate = mainKeys.stream()
                    .filter(key -> backupKeys.contains(key)) // 找到主 Redis 和备份 Redis 都有的键
                    .collect(Collectors.toList());

            // 备份主 Redis 中的键值对到备用 Redis
            keysToUpdate.forEach(key -> {
                String dataType = jedisMain.type(key);
                if (dataType.equals("string")) {
                    // 如果是字符串类型，备份字符串数据
                    String value = jedisMain.get(key);
                    // 判断备份 Redis 中是否已存在该键，并检查内容是否有变化
                    String backupValue = jedisBackup.get(key);
                    if (!StringUtils.equals(value, backupValue)) {
                        jedisBackup.set(key, value);
                        System.out.println("Update key: " + key);
                    }
                }
            });
        }
    }
}
